<template>
  <div class="setting">
    <el-card shadow="hover" class="layout-padding-auto">
      <TableSearch
        :search="state.search"
        @search="onSearch"
        @listenClick="listenClick"
      />
      <el-divider />
      <div class="setting__table">
        <div class="tree">
          <div class="tree-herder">
            <div class="title">备件库</div>
            <el-button
              type="primary"
              plain
              @click="addBJK"
              v-if="buttonDisplayOrNot(buttonCodes, 'partAddBJKBtn')"
            >
              <el-icon>
                <Plus />
              </el-icon>
              备件库
            </el-button>
          </div>
          <el-input v-model="filterText" placeholder="备件库搜索" />
          <el-tree
            ref="treeRef"
            :data="data"
            :props="defaultProps"
            @node-click="handleNodeClick"
            @node-drop="nodeDragEnter"
            default-expand-all
            :expand-on-click-node="false"
            :filter-node-method="filterNode"
            :indent="10"
            draggable
          >
            <template #default="{ node, data }">
              <span
                class="custom-tree-node show-hide"
                :class="{ active: currentNode.id == data.id }"
              >
                <span v-if="node.label.length > 8" class="treeLabel">{{
                  node.label
                }}</span>
                <span v-else>{{ node.label }}</span>
                <span class="operate">
                  <a
                    @click.stop="appendTree(data)"
                    v-if="buttonDisplayOrNot(buttonCodes, 'partAddBJKBtn')"
                  >
                    <el-icon><ele-Plus /></el-icon>
                  </a>
                  <a
                    style="margin-left: 8px"
                    @click.stop="editTree(data)"
                    v-if="buttonDisplayOrNot(buttonCodes, 'partEditBJKBtn')"
                  >
                    <el-icon><ele-Edit /></el-icon>
                  </a>
                  <el-popconfirm
                    width="150"
                    confirm-button-text="删除"
                    cancel-button-text="取消"
                    :icon="InfoFilled"
                    icon-color="#FC770A"
                    title="确定删除？"
                    @confirm="deleteTree(data)"
                  >
                    <template #reference>
                      <a
                        style="margin-left: 8px"
                        @click.stop=""
                        v-if="
                          buttonDisplayOrNot(buttonCodes, 'partDeleteBJKBtn')
                        "
                      >
                        <el-icon style="color: red"><ele-Delete /></el-icon>
                      </a>
                    </template>
                  </el-popconfirm>
                </span>
              </span>
            </template>
          </el-tree>
        </div>
        <AddBJK
          :bjDialog="bjDialog"
          :bjForm="bjForm"
          @quxiao="quxiao"
          @queren="queren"
        ></AddBJK>
        <Table
          ref="tableRef"
          v-bind="state.tableData"
          class="table-demo table"
          @delRow="onTableDelRow"
          @pageChange="onTablePageChange"
          @listenClick="listenClick"
        >
          <template #default="{ slotData, slotColumn }">
            <div v-if="slotColumn.key === 'qualityPeriod'">
              {{ slotData.qualityPeriod + slotData.qualityUnit }}
            </div>
          </template>
        </Table>
        <SpareDetail
          :detailDialog="detailDialog"
          :detailForm="detailForm"
          @closeDetail="closeDetail"
        ></SpareDetail>
        <OutBoundDialog
          :boundDialog="boundDialog"
          :boundForm="boundForm"
          :detailForm="detailForm"
          @cancelOut="cancelOut"
          @submitOut="submitOut"
        ></OutBoundDialog>
        <InBoundDialog
          :boundDialog="boundDialog2"
          :boundForm="boundForm"
          :detailForm="detailForm"
          @cancelIn="cancelIn"
          @submitIn="submitIn"
          @refreshBatch="refreshBatch"
        ></InBoundDialog>
      </div>
    </el-card>
  </div>
</template>
<script setup lang="ts">
import { Plus, MoreFilled, InfoFilled } from '@element-plus/icons-vue'
import { ElMessage, ElTree, ElNotification } from 'element-plus'
import { ref, reactive, defineAsyncComponent, watch, onMounted } from 'vue'
import {
  dictionaryList,
  addDictionary,
  editDictionary,
  deleteDictionary,
  updateDictionaryIdAndSortApi
} from '/@/api/publicApi'
import {
  downloadTemplateApi,
  getBatchApi,
  getSpareInfoApi,
  importPartExpertApi
} from '/@/api/spare/index'
import router from '/@/router'
import { buttonDisplayOrNot } from '../../utils/buttonBoolean'
import { getButtonListByRoleApi } from '/@/api/publicApi'
import { Session } from '/@/utils/storage'
import { debounce } from '/@/utils/loading'
const menu = Session.get('menu')
const buttonCodes = ref<any>([])
const Table = defineAsyncComponent(
  () => import('/@/components/table/index.vue')
)
const TableSearch = defineAsyncComponent(
  () => import('/@/components/table/search.vue')
)
const AddBJK = defineAsyncComponent(() => import('./components/AddBJK.vue'))
const SpareDetail = defineAsyncComponent(
  () => import('./components/SpareDetail.vue')
)
const OutBoundDialog = defineAsyncComponent(
  () => import('./components/OutBoundDialog.vue')
)
const InBoundDialog = defineAsyncComponent(
  () => import('./components/InBoundDialog.vue')
)
onMounted(() => {
  getBJK('')
  getSpareType()
  menu.forEach(async (element: any) => {
    if (element.menuUrl == '/spare/spareList') {
      let res = await getButtonListByRoleApi({
        terminalType: 1,
        menuPid: element.id
      })
      res.data.forEach((item: any) => {
        buttonCodes.value.push(item.buttonCode)
      })
    }
  })
})
// 定义变量内容
const tableRef = ref<RefType>()
const state = reactive<TableDemoState>({
  tableData: {
    flash: false, // 刷新表格
    // 表头内容（必传，注意格式）
    header: [
      { key: 'partNum', colWidth: '120', title: '备件编号', type: 'text' },
      { key: 'partName', colWidth: '120', title: '备件名称', type: 'text' },
      { key: 'partTypeName', colWidth: '120', title: '备件类型', type: 'text' },
      { key: 'realStock', colWidth: '120', title: '实际库存', type: 'text' },
      {
        key: 'safeStock',
        colWidth: '120',
        title: '最低安全库存',
        type: 'text'
      },
      { key: 'qualityPeriod', colWidth: '120', title: '保质期', type: 'slot' },
      {
        key: 'noticeUserName',
        colWidth: '120',
        title: '预警通知人',
        type: 'text'
      },
      { key: 'partUnit', colWidth: '120', title: '单位', type: 'text' },
      { key: 'remark', colWidth: '120', title: '备注', type: 'text' }
    ],
    columnBtn: [
      {
        name: 'details',
        text: '详情',
        type: 'success',
        hide(row: any): boolean {
          return true
        },
        btns: buttonCodes.value,
        btnCode: 'partDetailBtn'
      },
      {
        name: 'editPart',
        text: '编辑',
        color: '#1962E0',
        hide(row: any): boolean {
          return true
        },
        btns: buttonCodes.value,
        btnCode: 'partEditBtn'
      },
      {
        name: 'inBound',
        text: '入库',
        type: 'warning',
        hide(row: any): boolean {
          return true
        },
        btns: buttonCodes.value,
        btnCode: 'partInputBtn'
      },
      {
        name: 'outBound',
        text: '出库',
        type: 'primary',
        hide(row: any): boolean {
          return true
        },
        btns: buttonCodes.value,
        btnCode: 'partOutputBtn'
      },
      {
        name: 'usageRecord',
        text: '使用记录',
        type: 'danger',
        hide(row: any): boolean {
          return true
        },
        btns: buttonCodes.value,
        btnCode: 'partUsageRecordBtn'
      }
    ],
    // 配置项（必传）
    config: {
      listApi: '/device/mobile/devicePart/pageList',
      listHttp: 'post',
      total: 0, // 列表总数
      loading: true, // loading 加载
      noPage: false, // 是否分页
      isSerialNo: true, // 是否显示表格序号
      isSelection: false, // 是否显示表格多选
      isOperate: true, // 是否显示表格操作栏
      isExtend: false, // 是否可以扩展
      operateName: 'spare',
      operateWidth: '440', //操作栏宽度
      fixed: 'right' //操作栏固定
    },
    // 搜索参数
    param: {
      storehouseIds: [] // 必传参数，分页的不要传
    }
  },
  // 搜索表单，动态生成（传空数组时，将不显示搜索，注意格式）
  search: {
    param: [
      {
        label: '',
        prop: 'keyword',
        placeholder: '可输入备件编号/名称搜索',
        options: [],
        type: 'input'
      },
      {
        label: '备件类型',
        prop: 'partType',
        placeholder: '请选择',
        options: [],
        type: 'select'
      }
    ],
    btn: [
      {
        text: '新增',
        fun: 'addSpare',
        disable: false,
        loading: false,
        type: 'primary',
        hide(): boolean {
          return false
        },
        btns: buttonCodes.value,
        btnCode: 'partAddBtn'
      },
      {
        text: '批量导入备件',
        fun: 'batchImportPart',
        disable: false,
        loading: false,
        type: 'primary',
        hide(): boolean {
          return false
        },
        btns: buttonCodes.value,
        btnCode: 'partBatchExportBtn'
      },
      {
        text: '导入模板下载',
        fun: 'modeldnowLoad',
        disable: false,
        type: 'primary',
        hide(): boolean {
          return false
        },
        btns: buttonCodes.value,
        btnCode: 'partImportTemplateBtn'
      }
    ],
    reset: true
  }
})

interface Tree {
  id: string
  configValue: string
  children?: Tree[]
  customizeFlag: number
  parentId: string
}

const bjDialog = ref(false)
const detailDialog = ref(false)
const boundDialog = ref(false)
const boundDialog2 = ref(false)
const boundForm = ref<any>({
  boundTitle: '',
  boundType: '',
  outBatch: []
})
const detailForm = ref<any>({})
const bjLevel = ref(0)
const filterText = ref('')
const treeRef = ref<InstanceType<typeof ElTree>>()

const defaultProps = {
  children: 'children',
  label: 'configValue'
}

watch(filterText, (val) => {
  treeRef.value!.filter(val)
})

const filterNode = (value: string, data: Tree) => {
  if (!value) return true
  return data.configValue.includes(value)
}

const data = ref<Tree[]>([])
let currentNode: any = ref({
  id: '',
  configValue: '',
  children: [],
  customizeFlag: 0,
  parentId: ''
})
const getBJK = (val: any) => {
  let params = { configType: 'part_library', keyword: '' }
  dictionaryList(params).then((res) => {
    if (res.code == 0) {
      data.value = res.data
      if (data.value.length) {
        if (val == '') {
          currentNode.value = data.value[0]
        } else {
          currentNode.value = getDepth(data.value, val)
          console.log(currentNode.value)
        }
        handleNodeClick(currentNode.value)
        // state.tableData.param.storehouseIds.push(currentNode.value.id)
      }
    }
  })
}

// 递归，求树子项，用于默认选中
const getDepth = (arr: any, val: any) => {
  console.log(arr)
  console.log(val)
  let result
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].configValue == val) {
      result = arr[i]
      return result
    }
    if (arr[i].children && arr[i].children.length > 0) {
      result = getDepth(arr[i].children, val)
    }
    if (result) return result
  }
  return result
}

const getSpareType = () => {
  let params = { configType: 'part_type', keyword: '' }
  dictionaryList(params).then((res) => {
    if (res.code == 0) {
      state.search.param.forEach((i: any) => {
        if (i.prop == 'partType') {
          i.options = res.data
          i.options.unshift({
            configValue: '全部',
            customizeFlag: 0,
            id: '',
            parentId: '0'
          })
        }
      })
    }
  })
}

// 初始化列表数据
const getTableData = () => {
  state.tableData.flash = !state.tableData.flash
}
// 搜索点击时表单回调
const onSearch = (data: EmptyObjectType) => {
  state.tableData.param = Object.assign({}, state.tableData.param, { ...data })
  // console.log(state.tableData.param);
  state.tableData.flash = !state.tableData.flash
}
// 删除当前项回调
const onTableDelRow = (row: EmptyObjectType) => {
  ElMessage.success(`删除${row.name}成功！`)
  getTableData()
}
// 分页改变时回调
const onTablePageChange = (page: TableDemoPageType) => {
  state.tableData.param.pageNum = page.pageNum
  state.tableData.param.pageSize = page.pageSize
  getTableData()
}

const bjNodeId = ref('')
const bjParentId = ref('')
const bjForm = ref({
  title: '',
  name: ''
})

//添加节点
const appendTree = (data: any) => {
  bjLevel.value = 1
  bjNodeId.value = data.id
  bjParentId.value = data.id
  bjForm.value.title = '添加'
  bjForm.value.name = ''
  bjDialog.value = !bjDialog.value
}
//编辑节点
const editTree = (data: any) => {
  bjLevel.value = 1
  bjNodeId.value = data.id
  bjParentId.value = data.parentId
  bjForm.value.title = '编辑'
  bjForm.value.name = data.configValue
  bjDialog.value = !bjDialog.value
}

//删除节点
const deleteTree = (data: any) => {
  deleteDictionary(data.id).then((res) => {
    if (res.code == 0) {
      ElMessage({
        type: 'success',
        message: '删除成功'
      })
      getBJK('')
    }
  })
}

//添加备件库
const addBJK = () => {
  bjLevel.value = 0
  bjForm.value.title = '添加'
  bjParentId.value = '0'
  bjForm.value.name = ''
  bjDialog.value = !bjDialog.value
}
const queren = (val: any) => {
  if (bjLevel.value == 0) {
    bjkApi(0, val)
  } else {
    bjkApi(bjNodeId.value, val)
  }
}
const quxiao = () => {
  bjDialog.value = !bjDialog.value
}

const bjkApi = (id: any, val: any) => {
  let params = {
    parentId: bjParentId.value,
    configType: 'part_library',
    configName: val,
    configValue: val,
    id: id
  }
  if (bjForm.value.title == '添加') {
    addDictionary(params).then((res) => {
      if (res.code == 0) {
        ElMessage({
          type: 'success',
          message: '添加成功'
        })
        bjDialog.value = !bjDialog.value
        getBJK(val)
      }
    })
  } else {
    editDictionary(params).then((res) => {
      if (res.code == 0) {
        ElMessage({
          type: 'success',
          message: '编辑成功'
        })
        bjDialog.value = !bjDialog.value
        getBJK(val)
      }
    })
  }
}

const childArr = ref<any>([])
const handleNodeClick = (data: any) => {
  currentNode.value = data
  childArr.value = []
  getAllChild(data)
  childArr.value = childArr.value.filter(
    (item: any, index: any, array: any) => {
      return array.indexOf(item) === index
    }
  )
  state.tableData.param.storehouseIds = childArr.value
  getTableData()
}

const getAllChild = (obj: any) => {
  if (obj.children) {
    obj.children.forEach((item: any) => {
      childArr.value.push(item.id)
      getAllChild(item)
    })
  }
  childArr.value.push(obj.id)
}

const addSpare = () => {
  router.push({
    name: 'addSpare',
    query: {
      id: ''
    }
  })
}

const details = (row: any) => {
  getSpareInfoApi(row.id).then((res) => {
    if (res.code == 0) {
      detailForm.value = res.data
    }
  })
  detailDialog.value = !detailDialog.value
}
const closeDetail = () => {
  detailDialog.value = !detailDialog.value
}

//出库
const outBound = (row: any) => {
  getSpareInfoApi(row.id).then((res) => {
    if (res.code == 0) {
      detailForm.value = res.data
    }
  })
  boundForm.value.boundTitle = '备件出库'
  boundForm.value.boundType = '1'
  getBatchApi(row.id, '1').then((res) => {
    if (res.code == 0) {
      boundForm.value.outBatch = res.data
    }
  })
  boundDialog.value = !boundDialog.value
}
//入库
const inBound = (row: any) => {
  getSpareInfoApi(row.id).then((res) => {
    if (res.code == 0) {
      detailForm.value = res.data
    }
  })
  boundForm.value.boundTitle = '备件入库'
  boundForm.value.boundType = '2'
  getBatchApi(row.id, '2').then((res) => {
    if (res.code == 0) {
      boundForm.value.outBatch = res.data
    }
  })
  boundDialog2.value = !boundDialog2.value
}

const cancelOut = () => {
  boundDialog.value = !boundDialog.value
}
const submitOut = () => {
  boundDialog.value = !boundDialog.value
  getTableData()
}

const cancelIn = () => {
  boundDialog2.value = !boundDialog2.value
}

const submitIn = () => {
  boundDialog2.value = !boundDialog2.value
  getTableData()
}

const refreshBatch = (val: any) => {
  getBatchApi(val, '2').then((res) => {
    if (res.code == 0) {
      boundForm.value.outBatch = res.data
    }
  })
}

const usageRecord = (row: any) => {
  router.push({
    name: 'usageRecord',
    query: {
      id: row.id
    }
  })
}

const editPart = (row: any) => {
  router.push({
    name: 'addSpare',
    query: {
      id: row.id
    }
  })
}
//模板导出
let timer: any = null
const modeldnowLoad = () => {
  timer && clearTimeout(timer)
  timer = setTimeout(() => {
    downloadTemplateApi().then((res: any) => {
      let blob = new Blob([res], {
        type: 'application/vnd.ms-excel;charset=UTF-8'
      })
      let url = window.URL.createObjectURL(blob)
      const link = document.createElement('a') // 创建a标签
      link.download = '设备备件导入模板.xls'
      link.href = url
      link.click()
      URL.revokeObjectURL(url) // 释放内存
    })
  }, 1000)
}

const batchImportPart = () => {
  const fileType = ['xls', 'xlsx']
  const inputFile = document.createElement('input') as any
  inputFile.type = 'file'
  inputFile.style.display = 'none'
  document.body.appendChild(inputFile)
  inputFile.click()
  inputFile.addEventListener('change', () => {
    const file = inputFile.files[0]
    var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)

    if (!fileType.includes(testmsg)) {
      ElMessage.warning('上传的文件格式只能是excel文档')
      document.body.removeChild(inputFile)
      return false
    }
    //上传接口
    importPartExpertApi({ file: file }).then((res) => {
      if (res.code == 0) {
        ElNotification({
          title: '备件导入成功',
          message: '',
          type: 'success'
        })
        getTableData()
      }
    })
  })
}

const shebei = Session.get('shebei')
//拖拽移动进入摸节点
const nodeDragEnter = (node1: any, node2: any, wz: any, event: any) => {
  let params = {
    id: node1.data.id,
    parentId: node2.data.id,
    sort: 1,
    companyId: shebei.companyId
  }
  updateDictionaryIdAndSortApi(params).then((res) => {
    if (res.code == 0) {
      ElMessage.success('移动成功')
      getBJK(node1.data.configValue)
    }
  })
}

//定义方法对象 注意定义的方法 必须在上面已经申明 所以建议objFun申明和 listenClick方法 写在页面最下面
const objFun = {
  addSpare: addSpare,
  details: details,
  outBound: outBound,
  inBound: inBound,
  usageRecord: usageRecord,
  editPart: editPart,
  modeldnowLoad: modeldnowLoad,
  batchImportPart: batchImportPart
}
// 监听子级表格  传过来的方法
const listenClick = (name: string, val: any) => {
  objFun[name](val)
}
</script>
<style scoped lang="scss">
.setting {
  font-size: var(--el-font-size-base);

  &__table {
    display: flex;

    .tree {
      width: 15%;
      border-right: 1px solid rgba(217, 217, 217, 1);
      padding: 0px 10px;

      &-herder {
        display: flex;
        padding: 10px;
        justify-content: space-between;

        .title {
          line-height: 32px;
          font-size: var(--el-font-size-base);
          font-weight: 500;
        }
      }
    }

    .table {
      width: 85%;
      padding: 0px 10px;
    }
  }
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--el-font-size-base);
  padding-right: 8px;

  .treeLabel {
    width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.custom-tree-node:hover {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--el-font-size-base);
  padding-right: 8px;
  pointer-events: auto;

  .treeLabel {
    width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.show-hide :nth-child(2) {
  display: none;
}

.show-hide:hover :nth-child(2) {
  display: inline-block !important;
}

.operate {
  a {
    color: var(--el-color-primary);
  }
}

.active {
  color: var(--el-color-primary);
}

.el-divider--horizontal {
  margin: 10px 0 !important;
}
</style>
